/**************************************************************************
 * @name: common.c
 * @brief: 用于经常调用的模块
 * @date: 2025/01/15
 * @author: boluzs@163.com
 * @note: None
 * @version: 1.0.0
 * @Copyright (c) 2025 by boluzs@163.com, All Rights Reserved.
 **************************************************************************/
#include "main.h"
#include "bmp.h"
volatile int touch_keep_running = true;

/**************************************************************************
 * @name: Bmp_Show
 * @brief: BMP图片解码接口，会把图像显示在lcd上
 * @param {unsigned int} x_off:图片所在x轴偏移量
 * @param {unsigned int} y_off:图片所在y轴偏移量
 * @note: None
 * @retval: None
 **************************************************************************/
int Bmp_Show(char *filename, unsigned int *lcd_buf, unsigned int x_off, unsigned int y_off)
{
    // 1.读取图片和lcd文件
    FILE *bmp = fopen(filename, "rb");

    // 2.读取图片的大小以及宽高
    BmpInfo_t bmp_info;

    fseek(bmp, 18, SEEK_SET);
    fread(&bmp_info.width, 4, 1, bmp);
    fread(&bmp_info.height, 4, 1, bmp);
    fseek(bmp, 54, SEEK_SET);

    // 3.以行为单位循环读取BMP图片的颜色分量，并刷新到LCD
    char buf_line[bmp_info.width * 3];
    for (int y = 0; y < bmp_info.height; y++)
    {
        fread(buf_line, bmp_info.width * 3, 1, bmp);
        // 4.对每行不是4的倍数进行字节补齐
        fseek(bmp, BMP_LAST_BYTE(bmp_info.width), SEEK_CUR);
        for (int x = 0; x < bmp_info.width; x++)
        {
            // 5.BMP是小端存储，所以3个字节的颜色分量的顺序是BGR
            // *(lcd_mp + LCD_WIDTH * (LCD_HEIGHT - y - 1) + x) = buf_line[x * 3] + ((buf_line[x * 3 + 1]) << 8) + ((buf_line[x * 3 + 2]) << 16);
            lcd_buf[LCD_WIDTH * (LCD_HEIGHT - y_off - y - 1) + x + x_off] = (buf_line[3 * x]) |          // 将 24 位 RGB 数据转换为 32 位 ARGB 数据存储到 lcd_buf 中
                                                                            (buf_line[3 * x + 1] << 8) | // BMP 数据从左下角开始，这里进行翻转（y -> 479 - y）
                                                                            (buf_line[3 * x + 2] << 16);
        }
    }

    // 关闭文件和映射
    fclose(bmp);

    return 0;
}

/**************************************************************************
 * @name: Lcd_Refresh
 * @brief: 刷新屏幕内存映射
 * @param {unsigned int} *lcd_mp: 指的是lcd屏幕内存映射的起始地址，应该是mmap函数的返回值
 * @note: None
 * @retval: None
 **************************************************************************/
void Lcd_Refresh(unsigned int *lcd_mp, unsigned int *lcd_buf)
{
    memcpy(lcd_mp, lcd_buf, LCD_WIDTH * LCD_HEIGHT * 4);
}

/**************************************************************************
 * @name: Bmp_Sort
 * @brief: 排序BMP图片
 * @param {DIR} *dir_p:打开的目录后的directory stream objects
 * @param {dirent} *dirent_p:读取目录文件中的目录项
 * @param {char **} **file_names:排序后的文件名
 * @param {unsigned int *} *cnt:文件数量
 * @note: None
 * @retval: None
 **************************************************************************/
void Bmp_Sort(DIR *dir_p, struct dirent *dirent_p, char **file_names, unsigned int *cnt)
{
    int index = 0;
    while ((dirent_p = readdir(dir_p)) != NULL)
    {
        struct stat sb;
        stat(dirent_p->d_name, &sb);
        if (dirent_p->d_name[0] != '.' && (sb.st_mode & __S_IFMT) == __S_IFREG)
        {
            // 提取文件名中的数字部分
            sscanf(dirent_p->d_name, "Frame%d.bmp", &index);
            file_names[index] = dirent_p->d_name; // 保存文件名
            (*cnt)++;
        }
    }
}

/**************************************************************************
 * @name: Get_Ts
 * @brief: 通过触摸屏获取x，y操作
 * @note: None
 * @retval: None
 **************************************************************************/
void Get_Ts(void)
{
    int x = 0, y = 0;
    struct input_event ts_event;

    while (touch_keep_running)
    {
        int ret = read(touch_data.ts_fd, &ts_event, sizeof(ts_event));

        if (ts_event.type == EV_ABS && ts_event.code == ABS_X)
            x = ts_event.value;
        else if (ts_event.type == EV_ABS && ts_event.code == ABS_Y)
            y = ts_event.value;

        if (ts_event.type == EV_KEY && ts_event.code == BTN_TOUCH && ts_event.value == 0)
        {
            touch_data.ts_x = x;
            touch_data.ts_y = y;
            // printf("触摸松开，坐标: X = %d, Y = %d\n", touch_data.ts_x, touch_data.ts_y);
        }
    }
}
